<%@ page language="java" import="up7.*" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page import="java.io.*" %>
<%@ page import="up7.biz.folder.*" %>
<%@ page import="up7.biz.*" %>
<%@ page import="up7.model.*" %>
<%@ page import="up7.FileBlockWriter" %>
<%@ page import="up7.XDebug" %>
<%@ page import="java.util.*" %>
<%@ page import="net.sf.json.*" %>
<%@ page import="org.apache.commons.fileupload.FileItem" %>
<%@ page import="org.apache.commons.fileupload.FileItemFactory" %>
<%@ page import="org.apache.commons.fileupload.FileUploadException" %>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>
<%@ page import="org.apache.commons.lang.StringUtils" %>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.List"%>
<%
out.clear();
/*
	此页面负责将文件块数据写入文件中。
	此页面一般由控件负责调用
	参数：
		uid
		idSvr
		md5
		lenSvr
		RangePos
		fd_idSvr
		fd_lenSvr
	更新记录：
		2012-04-12 更新文件大小变量类型，增加对2G以上文件的支持。
		2012-04-18 取消更新文件上传进度信息逻辑。
		2012-10-25 整合更新文件进度信息功能。减少客户端的AJAX调用。
		2014-07-23 优化代码。
		2016-04-09 优化文件存储逻辑，增加更新文件夹进度逻辑
		2017-05-14 优化参数传递方式，改为使用head方式传递参数
		2017-08-15 精简和优化代码
*/
//String path = request.getContextPath();
//String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

String bd             = "";//
String uid            = "";
String id	 		  = "";// 		= request.getParameter("fid");
String pid	 		  = "";
String pidRoot		  = "";//文件夹标识(guid)
String perSvr 		  = "";// 	= request.getParameter("FileSize");
String lenSvr		  = "";
String lenLoc		  = "";
String nameLoc		  = "";
String sizeLoc		  = "";
String blockOffset 	  = "";// 	= request.getParameter("RangePos");
String blockIndex	  = "";//块偏移，相对于文件
String blockCount	  = "";//块总数
String blockSize	  = "";//块大小
String blockSizeLogic = "";//逻辑块大小（定义的块大小）
String blockMd5		  = "";//文件块md5值
String pathLoc		  = "";
String pathSvr		  = "";
String pathRel		  = "";
 
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
FileItemFactory factory = new DiskFileItemFactory();   
ServletFileUpload upload = new ServletFileUpload(factory);
List files = null;
try 
{
	files = upload.parseRequest(request);
} 
catch (FileUploadException e) 
{// 解析文件数据错误  
    out.println("read file data error:" + e.toString());
    return;
   
}

FileItem rangeFile = null;
// 得到所有上传的文件
Iterator fileItr = files.iterator();
// 循环处理所有文件
while (fileItr.hasNext()) 
{
	// 得到当前文件
	FileItem fd = (FileItem) fileItr.next();
	
	if(fd.isFormField())
	{
		String fn = fd.getFieldName();
		String fv = fd.getString();
		if(fn.equals("blockData")) bd = fv;
	}
	else{rangeFile = fd;}
}

CryptoTool ct         = new CryptoTool();
bd                    = ct.decrypt(bd);
JSONObject jv = JSONObject.fromObject(bd);

uid            = jv.getString("uid");
id             = jv.getString("id");// 		= request.getParameter("fid");
pid            = jv.getString("pid");
pidRoot        = jv.getString("pidRoot");//文件夹标识(guid)
perSvr         = jv.getString("perSvr");// 	= request.getParameter("FileSize");
lenSvr         = jv.getString("lenSvr");
lenLoc         = jv.getString("lenLoc");
nameLoc        = jv.getString("nameLoc");
sizeLoc        = jv.getString("sizeLoc");
blockOffset    = jv.getString("blockOffset");
blockIndex     = jv.getString("blockIndex");//块偏移，相对于文件
blockCount     = jv.getString("blockCount");//块总数
blockSize      = jv.getString("blockSize");//块大小
blockSizeLogic = jv.getString("blockSizeLogic");//逻辑块大小（定义的块大小）
blockMd5       = jv.getString("blockMd5");//文件块md5
pathLoc        = jv.getString("pathLoc");
pathSvr        = jv.getString("pathSvr");
pathRel        = jv.getString("pathRel");
pathLoc        = PathTool.url_decode(pathLoc);
nameLoc        = PathTool.url_decode(nameLoc);
pathSvr        = PathTool.url_decode(pathSvr);
pathRel        = PathTool.url_decode(pathRel);

//参数为空
if ( 	StringUtils.isBlank( lenLoc )
	|| 	StringUtils.isEmpty( uid )
	|| 	StringUtils.isBlank( id )
	|| 	StringUtils.isEmpty( blockOffset)
	||	StringUtils.isBlank( nameLoc ))
{
	XDebug.Output("lenLoc", lenLoc);
	XDebug.Output("uid", uid);
	XDebug.Output("id", id);
	XDebug.Output("nameLoc", nameLoc);
	XDebug.Output("pathLoc", pathLoc);
	XDebug.Output("fd-idSvr", pidRoot);
	XDebug.Output("param is null");
	return;
}

//验证文件块大小
if (rangeFile.getSize() != Integer.parseInt(blockSize)) 
{
	out.write("block size error");
	rangeFile.delete();
	return;
}

//文件块
if(StringUtils.isBlank(pidRoot))
{	
	//计算块MD5
	String rangeMd5="";
	if( !StringUtils.isBlank(blockMd5) ) rangeMd5 = Md5Tool.fileToMD5(rangeFile.getInputStream());
	
	//块MD5验证
	if( !StringUtils.isBlank(blockMd5) )
	{
		if(!rangeMd5.equals(blockMd5))
		{
			out.write("block md5 error");
			rangeFile.delete();
			return;
		}
	}
	
	//保存文件块
	FileBlockWriter fbw = new FileBlockWriter();	
	fbw.write(pathSvr,Long.parseLong(lenLoc),Long.parseLong(blockOffset),rangeFile);
	rangeFile.delete();
	
	//触发事件
    up7_biz_event.file_post_block(id, Integer.parseInt(blockIndex));
	
	//返回信息
	JSONObject res = new JSONObject();
	res.put("msg", "ok");
	res.put("md5", rangeMd5);	
	res.put("offset", Long.parseLong(blockOffset));//基于文件的块偏移位置
	out.write(res.toString());
}//子文件块
else
{
	FileInf fileSvr      = new FileInf();
	fileSvr.id           = id;
	File path_loc        = new File(pathLoc);
	fileSvr.nameLoc      = path_loc.getName();
	fileSvr.nameSvr      = nameLoc;
	fileSvr.lenLoc       = Long.parseLong( lenLoc );
	fileSvr.sizeLoc      = fileSvr.lenLoc<1024 ? PathTool.getDataSize(fileSvr.lenLoc) : sizeLoc;
	fileSvr.pathLoc      = pathLoc;
	fileSvr.pathSvr      = pathSvr;
	fileSvr.pathRel      = pathRel;
	fileSvr.pid          = pid;
	fileSvr.pidRoot      = pidRoot;
	fileSvr.blockCount   = Integer.parseInt(blockCount);
	fileSvr.blockSize    = Integer.parseInt(blockSize);
	
	//计算块MD5
	String rangeMd5="";
	if( !StringUtils.isBlank(blockMd5) ) rangeMd5 = Md5Tool.fileToMD5(rangeFile.getInputStream());
	
	//块MD5验证
	if( !StringUtils.isBlank(blockMd5) )
	{
		if(!rangeMd5.equals(blockMd5))
		{
			out.write("block md5 error");
			rangeFile.delete();
			return;
		}
	}
	
	//保存块
	FileBlockWriter fbw = new FileBlockWriter();
    fbw.write(fileSvr.pathSvr, fileSvr.lenLoc, Long.parseLong(blockOffset), rangeFile);
	rangeFile.delete();
	
	//触发事件
    up7_biz_event.file_post_block(id, Integer.parseInt(blockIndex));
	
	//返回信息
	JSONObject res = new JSONObject();
	res.put("msg", "ok");
	res.put("md5", rangeMd5);
	res.put("offset", Long.parseLong(blockOffset));//基于文件的块偏移位置
	out.write(res.toString());
}
%>